/*
 * Copyright (c) 2005, 2014 vacoor
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package org.vacoor.nothing.web.misc.license;

import java.math.BigInteger;
import java.security.spec.RSAKeyGenParameterSpec;
import java.util.Date;

/**
 * @author vacoor
 */
public abstract class LicenseKeygen {
    static BigInteger PRIVATE_EXP = new BigInteger("89126272330128007543578052027888001981", 10);
    static BigInteger MOD = new BigInteger("86f71688cdd2612ca117d1f54bdae029", 16);
    //    private static final BigInteger PRIVATE_EXP = new BigInteger("75812bde1f3725f1b6a228405c6ae2107e5697040fc59a7352bf8b3096cc65848b6ea53540453c788e74b4f48b745d8f00f22c182e36b1962004a9f4e3825eb9", 16);
//    private static final BigInteger MOD = new BigInteger("8a85d574eb2fe69f2cedebaf826e2206fdf9671ed55a3e40d54fdf23dbb7cbf4e2968618eef83a995d5dec55f47a935b4cb8329c3b8c56b92eb73188d730ad8b", 16);
    private static final BigInteger PUBLIC_EXP = RSAKeyGenParameterSpec.F4;
    public static final LicenseKeygen INSTANCE = new LicenseKeygen((byte) 0, (byte) 1, (byte) 13, (byte) 0) {
    };
    public static final LicenseKeygen IDEA = new LicenseKeygen((byte) 0, (byte) 1, (byte) 13, (byte) 0) {
    };

    protected final byte licenseType;
    protected final byte productType;
    protected final byte version;

    protected LicenseKeygen(byte licenseType, byte productType, byte majorVersion, byte minorVersion) {
        this.licenseType = licenseType;
        this.productType = productType;
        this.version = (byte) (majorVersion | (minorVersion << 4));
    }

    /**
     * @param customerId 客户id
     * @param name       用户名
     * @param days       有效期
     * @return
     */
    public String genLicenseKey(String name, int customerId, int days) {

        byte[] licenseBytes = new byte[12];
        // License 类型 | 产品类型
        licenseBytes[0] = (byte) ((licenseType & 0xF) | (productType & 0xF));
        // 产品版本
        licenseBytes[1] = version;
        // 生成日期
        long time = new Date().getTime() >> 16;
        licenseBytes[2] = (byte) (time & 0xFF);
        licenseBytes[3] = (byte) ((time >> 8) & 0xFF);
        licenseBytes[4] = (byte) ((time >> 16) & 0xFF);
        licenseBytes[5] = (byte) ((time >> 24) & 0xFF);
        // 有效天数
        licenseBytes[6] = (byte) (days & 0xFF);
        licenseBytes[7] = (byte) (days >> 8 & 0xFF);
        //
        licenseBytes[8] = 105;
        licenseBytes[9] = -59;
        // 校验位, (CRC32)
        short checksum = LicenseUtil.calculateCRC32(name, customerId, licenseBytes);
        licenseBytes[10] = (byte) (checksum & 0xFF);
        licenseBytes[11] = (byte) ((checksum >> 8) & 0xFF);
        //
        BigInteger encodedKey = new BigInteger(licenseBytes).modPow(PRIVATE_EXP, MOD);
        String licenseKey = LicenseUtil.encodeGroups(encodedKey);
        // 9EINM-OUZS1-B4QQ6-5FKLM-ELS2V-S9L4B-S1BMR-ZWEZF-OP5QV-QSHB8-8LHKA-V05C4-DLNIM-C10T7-TZP8Q-KGEBH-7CU29-F9DIV-7J4CA-PBIE0

        // 前面追加客户 id
        StringBuilder key = new StringBuilder();
        key.append(customerId);
        while (key.length() < 5) {
            key.insert(0, '0');
        }
        key.append("-").append(licenseKey);
        return key.toString();
    }

    public static void main(String[] args) throws InvalidLicenseException {
        String licenseKey = LicenseKeygen.INSTANCE.genLicenseKey("vacoor", 1, 10);
        LicenseInfo license = LicenseDecoder.decodeLicenseKey("vacoor", licenseKey);
        System.out.println(license);
    }
}
